﻿using ExcelSysLibs;
using ExcelSysLibs.OpenXml;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ToExcel
{
    internal class GlobalSetting
    {
        static GlobalSetting()
        {
            if (Current == null)
            {
                LoadSetting("配置.xlsx");
            }
        }
        internal static SettingReader Current { get; set; }
        internal static string OutputPath { get; set; }
        internal static IDictionary<string, string[]> OutputCache { get; set; }
        internal static void LoadSetting(string path)
        {
            var reader = new SettingReader();
            reader.Read(path);
            if (reader.LoadOK)
            {
                Current = reader;
            }
        }
        internal static void StartExport()
        {
            OutputPath = $"{Current.Configs["导出后文件名"]}{DateTime.UtcNow.ToString(Current.Configs["流水号格式"])}.xlsx";
            OutputCache = new Dictionary<string, string[]>();
        }
        internal static void EndExport()
        {
            Dictionary<string, object> runtime;
            var runtimes = new Dictionary<string, object>[OutputCache.Count];

            var keys = OutputCache.Keys.ToArray();
            for (var no= 0; no < OutputCache.Count; no ++)
            {
                var key = keys[no];
                runtime = new Dictionary<string, object>();
                for(var i = 0; i < Current.Template.Length; i++)
                {
                    if (Current.PropertyFormats.Keys.Contains(Current.TemplateTrueName[i]))
                    {
                        if (OutputCache[key][i] == null || OutputCache[key][i] == "-")
                        {
                            runtime.Add(Current.Template[i], OutputCache[key][i]);
                            continue;
                        }
                        switch (Current.PropertyFormats[Current.TemplateTrueName[i]])
                        {
                            case "数字":
                                var number_text = "";
                                for (var j = 0; j < OutputCache[key][i].Length; j++)
                                {
                                    if (Current.Configs["数字去除符号"].ToArray().Contains(OutputCache[key][i][j])) continue;
                                    number_text += OutputCache[key][i][j];
                                }
                                runtime.Add(Current.Template[i], decimal.Parse(number_text));
                                break;
                            case "日期":
                                runtime.Add(Current.Template[i], DateTime.Parse(OutputCache[key][i]));
                                break;
                            case "不记录":
                                break;
                            case "文本":
                            default: goto TEXT;
                        }
                        continue;
                    }
                    TEXT:
                    runtime.Add(Current.Template[i], GetTextFiltered(OutputCache[key][i]));

                }
                runtimes[no] = runtime;
            }
            ExcelSys.SaveAs(OutputPath, runtimes, configuration: new OpenXmlConfiguration
            {
                IgnoreTemplateParameterMissing = true
            });
        }
        private static string GetTextFiltered(string text)
        {
            if (text == null) goto END;
            if (!Current.Configs.ContainsKey("结果去除特定字")) goto END;
            if (Current.Configs["结果去除特定字"] == null) goto END;
            var texts = Current.Configs["结果去除特定字"].Split('\\');
            foreach (var i in texts)
            {
                text = text.Replace(i, "");
            }
            END:
            return text;
        }
        private static void UpdateByPrimaryKey(IDictionary<string, string> input)
        {
            if (input.ContainsKey(Current.Configs["主键"]))
            {
                if (! OutputCache.ContainsKey(input[Current.Configs["主键"]]))
                {
                    OutputCache.Add(input[Current.Configs["主键"]], new string[Current.Template.Length]);
                }
                for (var i = 0; i <Current.Template.Length; i++)
                {
                    if (input.ContainsKey(Current.TemplateTrueName[i]))
                    {
                        OutputCache[input[Current.Configs["主键"]]][i] = input[Current.TemplateTrueName[i]];
                    }
                }
            }
        }
        internal static void Export(string input)
        {
            var text = input.Split('\r', '\n', '\t')
                .Select(item => item.Trim())
                .Where(item => item != string.Empty)
                .ToArray();

            Dictionary<string, string> infos = new Dictionary<string, string>();
            for (var i = 0; i < text.Length; i++)
            {
                var single = text[i];

                foreach (var propertyDetail in Current.SinglePropertyDetails.Values) 
                {
                    if (single.Length <= propertyDetail["数据名称"].Length) continue;
                    if (propertyDetail["数据名称"] == single) goto REC_PROPERTY;
                    if (propertyDetail["数据名称"] == single.Substring(0, propertyDetail["数据名称"].Length))
                    {

                        if (propertyDetail["可能出现的后缀"].Split('\\').Contains(single.Substring(propertyDetail["数据名称"].Length))) goto REC_PROPERTY;
                    }
                    continue;
                REC_PROPERTY:
                    if (propertyDetail["过滤值"] != null && propertyDetail["过滤值"].Split('\\').Contains(text[i + 1])) continue;
                    var length_limit = propertyDetail["最小长度"];
                    if (length_limit != null && length_limit != "")
                    {
                        if (text[i + 1].Length > int.Parse(length_limit))
                        {
                            infos[propertyDetail["数据名称"]] = text[i + 1];
                            i++;
                        }
                    }
                    else
                    {
                        infos[propertyDetail["数据名称"]] = text[i + 1];
                        i++;
                    }

                    continue;
                }

                foreach (var table in Current.Tables)
                {
                    if (table["起始列名"] != single) continue;
                    var j = i ;
                    var columns = new List<string>();
                    columns.Add(single);
                    while (text[++j - 1] != table["结尾列名"])
                    {
                        if (text[j] == table["起始列名"]) columns.Clear();
                        columns.Add(text[j]);
                    }

                    Dictionary<string, string> runtime = new Dictionary<string, string>();
                    var row = 0;
                    var singleExist = false;
                    while (j <= (text.Length - columns.Count))
                    {
                        if (text[j] == table["无数据标识"]) break;
                        if (text[j] == table["数据结束"]) break;
                        if (table["结束忽略空格后内容"] == "是" && text[j].Split(' ')[0] == table["数据结束"]) break;

                        runtime.Clear();
                        if (table["行转列"] == "是") goto COLUMN;
                        for (var ii = 0; ii < columns.Count; ii++)
                        {
                            runtime.Add($"{columns[ii]}", text[j++]);
                        }
                        UpdateByPrimaryKey(runtime);
                        continue;
                    COLUMN:
                        for ( var ii = 0; ii < columns.Count; ii++)
                        {
                            runtime[columns[ii]] = text[j++];
                        }
                        if (table["存在单个数据"] == "是")
                        {
                            var tmp = table["单个数据逻辑"].Split('=');
                            if (runtime[tmp[0]] == tmp[1])
                            {
                                if (table["单个数据只取一次"] != "是" || !singleExist)
                                {
                                    singleExist = true;
                                    foreach (var tmp1 in runtime.Keys)
                                    {
                                        if (tmp1 == tmp[0]) continue;
                                        infos.Add($"{tmp1}", runtime[tmp1]);
                                    }
                                    continue;
                                }
                            }
                        }

                        row++;
                        foreach (var tmp in runtime.Keys)
                        {
                            infos.Add($"{table["表名"]}{row}{tmp}", runtime[tmp]);
                        }
                        continue;
                    }
                    i = j;
                }
            }
            UpdateByPrimaryKey(infos);
        }
    }
}
